using System;

namespace CL
{
    public interface ICLAwake
    {
    }

    public interface ICLAwake<A>
    {
    }

    public interface ICLAwake<A, B>
    {
    }

    public interface ICLAwake<A, B, C>
    {
    }

    public interface ICLAwake<A, B, C, D>
    {
    }

    public interface ICLAwakeSystem : ICLSystemType
    {
        void Run(CLEntity o);
    }

    public interface ICLAwakeSystem<A> : ICLSystemType
    {
        void Run(CLEntity o, A a);
    }

    public interface ICLAwakeSystem<A, B> : ICLSystemType
    {
        void Run(CLEntity o, A a, B b);
    }

    public interface ICLAwakeSystem<A, B, C> : ICLSystemType
    {
        void Run(CLEntity o, A a, B b, C c);
    }

    public interface ICLAwakeSystem<A, B, C, D> : ICLSystemType
    {
        void Run(CLEntity o, A a, B b, C c, D d);
    }

    public abstract class CLAwakeSystem<T> : CLSystemObject, ICLAwakeSystem where T : CLEntity, ICLAwake
    {
        public int GetInstanceQueueIndex()
        {
            return CLInstanceQueueIndex.None;
        }

        public void Run(CLEntity o)
        {
            this.Awake((T)o);
        }

        public Type SystemType()
        {
            return typeof(ICLAwakeSystem);
        }

        public Type Type()
        {
            return typeof(T);
        }

        protected abstract void Awake(T self);
    }

    public abstract class CLAwakeSystem<T, A> : CLSystemObject, ICLAwakeSystem<A> where T : CLEntity, ICLAwake<A>
    {
        public int GetInstanceQueueIndex()
        {
            return CLInstanceQueueIndex.None;
        }

        public void Run(CLEntity o, A a)
        {
            this.Awake((T)o, a);
        }

        public Type SystemType()
        {
            return typeof(ICLAwakeSystem<A>);
        }

        public Type Type()
        {
            return typeof(T);
        }

        protected abstract void Awake(T self, A a);
    }


    public abstract class AwakeSystem<T, A, B, C> : CLSystemObject, ICLAwakeSystem<A, B, C> where T : CLEntity, ICLAwake<A, B, C>
    {
        public int GetInstanceQueueIndex()
        {
            return CLInstanceQueueIndex.None;
        }

        public void Run(CLEntity o, A a, B b, C c)
        {
            this.Awake((T)o, a, b, c);
        }

        public Type SystemType()
        {
            return typeof(ICLAwakeSystem<A, B, C>);
        }

        public Type Type()
        {
            return typeof(T);
        }

        protected abstract void Awake(T self, A a, B b, C c);
    }

    public abstract class AwakeSystem<T, A, B, C, D> : CLSystemObject, ICLAwakeSystem<A, B, C, D> where T : CLEntity, ICLAwake<A, B, C, D>
    {
        public int GetInstanceQueueIndex()
        {
            return CLInstanceQueueIndex.None;
        }

        public void Run(CLEntity o, A a, B b, C c, D d)
        {
            this.Awake((T)o, a, b, c, d);
        }

        public Type SystemType()
        {
            return typeof(ICLAwakeSystem<A, B, C, D>);
        }

        public Type Type()
        {
            return typeof(T);
        }

        protected abstract void Awake(T self, A a, B b, C c, D d);
    }

}
